#pragma once
#include <iostream>
#include <string>
#include <memory>
#include <jsoncpp/json/json.h>
#include <functional>
#include "Socket.hpp"

using namespace SocketModule;
using namespace std;

class Request
{
public:
    Request()
    {
    }

    Request(int x, int y, char oper)
        : _x(x),
          _y(y),
          _oper(oper)
    {
    }

    string Serialize()
    {
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["oper"] = _oper;
        Json::FastWriter writer;
        string s = writer.write(root);
        return s;
    }

    bool DeSerialize(string &in)
    {
        Json::Value root;
        Json::Reader reader;
        bool ok = reader.parse(in, root);
        if (ok)
        {
            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _oper = root["oper"].asInt();
        }
        return ok;
    }

    ~Request() {}
    int X() { return _x; }
    int Y() { return _y; }
    char Oper() { return _oper; }

private:
    int _x;
    int _y;
    char _oper;
};

class Response
{
public:
    Response()
    {
    }
    Response(int code, int result)
        : _code(code),
          _result(result)
    {
    }

    string Serialize()
    {
        Json::Value root;
        root["code"] = _code;
        root["result"] = _result;
        Json::FastWriter writer;
        string s = writer.write(root);
        return s;
    }

    bool DeSerialize(string &in)
    {
        Json::Value root;
        Json::Reader reader;
        bool ok = reader.parse(in, root);
        if (ok)
        {
            _code = root["code"].asInt();
            _result = root["result"].asInt();
        }
        return ok;
    }

    ~Response() {}
    void SetResult(int res)
    {
        _result = res;
    }
    void SetCode(int code)
    {
        _code = code;
    }
    void ShowResult()
    {
        std::cout << "计算结果是: " << _result << "[" << _code << "]" << std::endl;
    }

private:
    int _code;
    int _result;
};

const string sep = "/r/n";

using func_t = function<Response(Request &req)>;

class Protocol
{
public:
    Protocol() {}
    Protocol(func_t func)
        : _func(func)
    {
    }

    string Encode(const string &jsonstr)
    {
        string len = to_string(jsonstr.size());
        return len + sep + jsonstr + sep;
    }

    bool Decode(string &buffer, string *package)
    {
        ssize_t pos = buffer.find(sep);
        if (pos == string::npos)
            return false;
        string package_len = buffer.substr(0, pos);
        int package_len_int = stoi(package_len);
        int target_len = package_len_int + sep.size() * 2 + package_len.size();
        if (buffer.size() < target_len)
            return false;
        *package = buffer.substr(pos + sep.size(), package_len_int);
        buffer.erase(0, target_len);
        return true;
    }

    void GetRequest(shared_ptr<Socket> &sock, InetAddr &client)
    {
        string buffer_queue;
        while (true)
        {
            int n = sock->Recv(&buffer_queue); // 成功
            if (n > 0)
            {
                std::cout << "-----------request_buffer--------------" << std::endl;
                std::cout << buffer_queue << std::endl;
                std::cout << "------------------------------------" << std::endl;
                string json_package;
                while (Decode(buffer_queue, &json_package))
                {
                    cout << "-----------request_json--------------" << std::endl;
                    cout << json_package << std::endl;
                    cout << "------------------------------------" << std::endl;

                    cout << "-----------request_buffer--------------" << std::endl;
                    cout << buffer_queue << std::endl;
                    cout << "------------------------------------" << std::endl;

                    LOG(LogLevel::DEBUG) << client.StringAddr() << " 请求: " << json_package;
                    Request resq;
                    // 这里错误
                    bool ok = resq.DeSerialize(json_package);
                    if (!ok)
                        continue;

                    Response rep = _func(resq); // 应该是计算结果然后状态码返回给Response

                    string jsonstr = rep.Serialize();

                    string send_str = Encode(jsonstr);

                    sock->Send(send_str); // 失败
                }
            }
            else if (n == 0)
            {
                LOG(LogLevel::INFO) << "client:" << client.StringAddr();
                break;
            }
            else
            {
                LOG(LogLevel::FATAL) << "client" << client.StringAddr() << ",recv error";
                break;
            }
        }
    }

    bool GetResponse(shared_ptr<Socket> &client, string &resp_buff, Response *resp)
    {
        while (true)
        {
            int n = client->Recv(&resp_buff);
            if (n > 0)
            {
                string json_package;
                while (Decode(resp_buff, &json_package))
                {
                    resp->DeSerialize(json_package);
                }
                return true;
            }
            else if (n == 0)
            {
                std::cout << "server quit " << std::endl;
                return false;
            }
            else
            {
                std::cout << "recv error" << std::endl;
                return false;
            }
        }
    }

    string BuildRequestString(int x, int y, char oper)
    {
        // 1. 构建一个完整的请求
        Request req(x, y, oper);

        // 2. 序列化
        std::string json_req = req.Serialize();

        return Encode(json_req);
    }

    ~Protocol()
    {
    }

private:
    func_t _func;
};